mod error;
mod util;

use clap::{Arg, ArgAction, Command};
use common::model::{NpmModuleInfo, ProjectDirInfo};
use common::util::{init_project_api_json, run_gen_api, merge_api_json};
use std::path::Path;
use tokio::signal;
use tokio::task;

use util::{
    async_launch_project, copy_module_to_project, init_project, load_package_json,
    run_config_features, run_module_dev_sync, setup_code, setup_dir,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let matches = Command::new("module_dev")
        .version("0.1.0")
        .author("caozongying<zongying_cao@163.com>")
        .about("caozongying_cao<zongying_cao@163.com> is the author of module_dev")
        .arg(
            Arg::new("config")
                .short('c')
                .long("config")
                .value_name("CONFIG_FILE_PATH")
                .help("配置文件的路径")
                .action(ArgAction::Set),
        )
        .get_matches();

    let config_file_path = Path::new(
        matches
            .get_one::<String>("config")
            .expect("无法获取config的文件路径"),
    );

    let module_dir_info = ProjectDirInfo::new(&std::env::current_dir()?);
    let temp_dir = setup_dir()?;


    let temp_project_dir = init_project(&temp_dir)?;
    let temp_project_dir_info = ProjectDirInfo::new(&temp_project_dir);

    copy_module_to_project(&module_dir_info, &temp_project_dir_info)?;
    load_package_json(&temp_project_dir)?;

    let api_json_path = init_project_api_json(&temp_project_dir)?;
    setup_code(&temp_project_dir)?;

    merge_api_json(&api_json_path, &NpmModuleInfo::new_for_dev(&std::env::current_dir()?))?;

    run_gen_api(config_file_path, &temp_project_dir, &api_json_path)?;
    run_config_features(
        &config_file_path.to_string_lossy(),
        &temp_project_dir.to_string_lossy(),
    )?;

    // 启动 async_launch_project 和 run_module_dev_sync
    let async_launch_handle =
        task::spawn(async move { async_launch_project(temp_project_dir.clone()).await });
    let run_module_dev_sync_handle = task::spawn(async move {
        run_module_dev_sync(module_dir_info.clone(), temp_project_dir_info.clone()).await
    });

    // 等待 Ctrl+C 信号
    signal::ctrl_c().await?;
    println!("Received Ctrl+C, terminating...");

    // 终止 async_launch_project 和 run_module_dev_sync
    async_launch_handle.abort();
    run_module_dev_sync_handle.abort();

    println!("Terminated all tasks.");

    Ok(())
}
